#pragma once

#include <WinSock2.h>
#include <MSWSock.h>

namespace ysimple_network
{
	class YWinSockEx
	{
		LPFN_ACCEPTEX					lpfnAcceptEx;
		LPFN_DISCONNECTEX			lpfnDisconnectEx;
		LPFN_GETACCEPTEXSOCKADDRS	lpfnGetAcceptExSocketAddrs;
		LPFN_CONNECTEX				lpfnConnectEx;
		LPFN_TRANSMITFILE			lpfnTransmitFile;
	public:
		YWinSockEx(void);
		~YWinSockEx(void);

		static YWinSockEx&	getInstance();

		HRESULT StartUp();

		HRESULT GetExtentionWinsockApi( GUID& apiGuid, LPVOID* lpWinsockApiFunction );

		BOOL AcceptEx(
			__in   SOCKET sListenSocket,
			__in   SOCKET sAcceptSocket,
			__in   PVOID lpOutputBuffer,
			__in   DWORD dwReceiveDataLength,
			__in   DWORD dwLocalAddressLength,
			__in   DWORD dwRemoteAddressLength,
			__out  LPDWORD lpdwBytesReceived,
			__in   LPOVERLAPPED lpOverlapped
			);

		BOOL DisconnectEx(
			__in  SOCKET hSocket,
			__in  LPOVERLAPPED lpOverlapped,
			__in  DWORD dwFlags,
			__in  DWORD reserved
			);

		void GetAcceptExSockaddrs(
			__in   PVOID lpOutputBuffer,
			__in   DWORD dwReceiveDataLength,
			__in   DWORD dwLocalAddressLength,
			__in   DWORD dwRemoteAddressLength,
			__out  LPSOCKADDR *LocalSockaddr,
			__out  LPINT LocalSockaddrLength,
			__out  LPSOCKADDR *RemoteSockaddr,
			__out  LPINT RemoteSockaddrLength
			);

		BOOL PASCAL ConnectEx(
			__in      SOCKET s,
			__in      const struct sockaddr *name,
			__in      int namelen,
			__in_opt  PVOID lpSendBuffer,
			__in      DWORD dwSendDataLength,
			__out     LPDWORD lpdwBytesSent,
			__in      LPOVERLAPPED lpOverlapped
			);

		BOOL TransmitFile(
			SOCKET hSocket,
			HANDLE hFile,
			DWORD nNumberOfBytesToWrite,
			DWORD nNumberOfBytesPerSend,
			LPOVERLAPPED lpOverlapped,
			LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
			DWORD dwFlags
			);
	};

}

